24 de maio, 2021

Airbnb é um serviço online comunitário para as pessoas anunciarem, descobrirem e reservarem acomodações e meios de hospedagem.
Este sistema permite aos indivíduos alugar o todo ou parte de sua própria casa, como uma forma de acomodação extra. O site fornece uma plataforma de busca e reservas entre a pessoa que oferece a acomodação e o turista que busca pela locação. Abrange mais de 500 mil anúncios em mais de 35.000 cidades e 192 países. Desde sua criação em Novembro de 2008 até Junho de 2012, mais de 10 milhões de reservas foram agendadas via Airbnb.
Os dados por trás do site Inside Airbnb são obtidos de informações publicamente disponíveis no site do Airbnb. Os dados foram analisados, limpos e agregados para facilitar a discussão pública. E nesta análise, este assunto será o tema principal.
Objetivo: Utilizar a linguagem Python, para prever o tipo de acomodação escolhido pelos clientes.
Começaremos nosso projeto, instalando e importanto todas as bilbiotecas necessárias, para a realização das fases iniciais de exploração, e transformação dos dados (Data Munging).
# Instalando bibliotecas necessárias para a análise.
!pip3 install phik association_metrics as am
# Instalando pacote wget (no ambiente anaconda).
#!conda install -c menpo wget -y
# Importando biblioteca, para ocultar Future Warnings.
import warnings
from sklearn.exceptions import ConvergenceWarning
warnings.simplefilter(action = 'ignore', category = FutureWarning)
warnings.simplefilter(action = 'ignore', category = ConvergenceWarning)
warnings.simplefilter(action = 'ignore', category = UserWarning)
# Importando biblioteca para manipular funcionalidades do sistema operacional.
import os
# Importando bibliotecas, para a manipulação e exploração dos conjuntos de dados.
import numpy as np
import pandas as pd
# Importando bibliotecas, para tarefas de Data Munging.
from sklearn.feature_selection import VarianceThreshold
# Importando bibliotecas, para a plotagem de gráficos interativos com o plotly.
import plotly.offline as py
import plotly.graph_objs as go
import plotly.figure_factory as ff
py.init_notebook_mode(connected = False)
# Importando bibliotecas, para a plotagem de gráficos com o Seaborn e Matplotlib.
import seaborn as sns
import matplotlib.pyplot as plt
# Importando classes e bibliotecas, para a etapa de pré-processamento dos dados.
from sklearn import preprocessing
from sklearn.preprocessing import MinMaxScaler, PowerTransformer, normalize, LabelEncoder, StandardScaler
# Importando classes para calcular algumas estatísticas.
from scipy.stats import kurtosis, skew
# Importando biliotecas, para a fase de Feature Selection.
from sklearn.decomposition import PCA
from mlxtend.feature_selection import SequentialFeatureSelector as SFS
from sklearn.feature_selection import SelectKBest, SelectPercentile, mutual_info_classif, f_classif, RFE, chi2
# Importando bibliotecas, para a etapa de modelagem preditiva.
import xgboost as xgb
from sklearn import tree
from sklearn.svm import SVC
from sklearn.naive_bayes import GaussianNB
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression, RidgeClassifierCV
from sklearn.model_selection import KFold, cross_val_score, train_test_split
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis, QuadraticDiscriminantAnalysis
from sklearn.ensemble import RandomForestClassifier, ExtraTreesClassifier, AdaBoostClassifier, GradientBoostingClassifier
# Importando Classe, para carregar e salvar modelos preditivos em arquivos externos.
import pickle
# Importando Classe, para fazer a busca dos melhores parâmetros, a serem utilizados em cada um dos modelos treinados.
from sklearn.model_selection import GridSearchCV
# Importando Classes, para calcular as métricas de avaliação dos modelos preditivos.
from sklearn.metrics import accuracy_score, log_loss
# Criando um dicionário para armazenar o nome das pastas necessárias para a análise.
FOLDERS = {
'dir' : 'content',
'input' : 'inputs',
'output': 'outputs'
}
# Definindo a hierarquia entre as pastas.
PATHS = {
'dir' : FOLDERS['dir'],
'input' : '/'.join([FOLDERS['dir'], FOLDERS['input']]),
'output': '/'.join([FOLDERS['dir'], FOLDERS['output']])
}
# Criando a pasta raíz caso não exista.
if not os.path.exists(PATHS['dir']):
os.mkdir(PATHS['dir'])
# Criando a pasta de input caso não exista.
if not os.path.exists(PATHS['input']):
os.mkdir(PATHS['input'])
# Criando a pasta de ouputs caso não exista.
if not os.path.exists(PATHS['output']):
os.mkdir(PATHS['output'])
# Baixando o conjunto de dados que será analisado.
!wget http://data.insideairbnb.com/brazil/rj/rio-de-janeiro/2021-03-21/visualisations/listings.csv
# Gerando uma lista com todos os arquivos presentes na pasta Raíz do projeto.
files = os.listdir()
# Criando uma lista para armazenar o nome dos arquivos .csv existentes no diretório raíz.
dataFiles = []
# Capturando o nome de todos os arquivos .csv presentes no diretório raíz.
for f in files:
if f[-4:] == '.csv':
dataFiles.append(f)
# Movendo os arquivos .csv identificados para o diretório de inputs.
for f in dataFiles:
if not os.path.exists('/'.join([PATHS['input'], f])):
os.rename(f, '/'.join([PATHS['input'], f]))
# Carregando conjunto de dados.
data = pd.read_csv('/'.join([PATHS['input'], 'listings.csv']))
# Criando um dicionário para armazenar a linhagem do conjunto de dados
allData = {'raw': data.copy()}
# Exibindo as primeiras linhas do DataFrame.
data.head()
Antes de prosseguirmos, é importante destacar a informação que cada variável representa:
| Variável | Tipo | Descrição |
|---|---|---|
| id | int64 | Identificador exclusivo do Airbnb para o anúncio; |
| name | object | Nome da lista; |
| host_id | int64 | Identificador único do Airbnb para o host/usuário; |
| host_name | object | Nome do host. Normalmente, apenas o(s) primeiro(s) nome(s); |
| neighbourhood_group | float64 | Sem informações; |
| neighbourhood | object | O grupo de vizinhança foi geocodificado usando a latitude e longitude em comparação com as vizinhanças definidas por shapefiles digitais abertos ou públicos; |
| latitude | float64 | Usa a projeção do Sistema Geodésico Mundial (WGS84) para latitude. |
| longitude | float64 | Usa a projeção do Sistema Geodésico Mundial (WGS84) para longitude. |
| room_type (Target) | object | Define o tipo da hospedagem. Existem 4 tipos: Entire home/ apt, Private room, Shared room e Hotel room ; |
| price | int64 | Preço diário na moeda local; |
| minimum_nights | int64 | Número mínimo de noites para a listagem (as regras do calendário podem ser diferentes); |
| number_of_reviews | int64 | O número de comentários que a listagem tem; |
| last_review | object | A data da última/mais recente revisão; |
| reviews_per_month | float64 | O número de comentários que a listagem teve durante sua vida útil; |
| calculated_host_listings_count | int64 | O número de listagens de casa/apartamentos inteiras que o anfitrião tem no scrape atual, na geografia da cidade/região e; |
| availability_365 | int64 | Disponibilidade da lista x dias no futuro, conforme determinado pelo calendário. |
# Verificando as dimensões do dataset.
data.shape
Verificamos a existência de 16 variáveis, e 26.628 observações dentro do dataset.
# Verificando o número de registros duplicados.
data.duplicated().sum()
Não há registros duplicados dentro do conjunto de dados.
# Verificando o número de NAs existentes dentro do dataset.
data.isna().sum()
Há valores nulos dentro do conjunto de dados.
# Verificando o tipo de dados das variáveis do dataset.
data.dtypes.value_counts()
Todas as variáveis do conjunto de dados, foram classificadas como sendo do tipo de dado Int64, Object e float64.
# Contabilizando o número de valores únicos em cada variável do dataset.
info = data.nunique().sort_values()
# Determinando o tipo de dado de cada uma das variáveis do dataset.
info = pd.DataFrame(info.values, index = info.index, columns = ['NUniques'])
# Atribuindo informações sobre o tipo de dado das variáveis ao DataFrame.
info['dtypes'] = data.dtypes
# Exibindo Dataframe.
info
Todas as variáveis preditoras, apresentam um grande número de valores únicos.
Iremos definir algumas funções, para padronizar as plotagens de gráficos que criaremos.
Para fazer plotagens offline com o plotly (isto é, em ambientes como o Google Colab, Azure, Kaggle, Nteract, etc.), precisamos definir a função a seguir, e chamá-la sempre que formos gerar um gráfico.
# Definindo uma função, para plotar gráficos interativos, em um ambiente jupyter não-padrão.
def configure_plotly_browser_state():
import IPython
display(IPython.core.display.HTML('''
<script src="/static/components/requirejs/require.js"></script>
<script>
requirejs.config({
paths: {
base: '/static/base',
plotly: 'https://cdn.plot.ly/plotly-1.43.1.min.js?noext',
},
});
</script>
'''))
Os gráficos de distribuição são usados para mostrar como as variáveis são distribuídas ao longo do tempo, ajudando a identificar valores discrepantes e tendências.
# Definindo uma função, para criar gráficos de Boxplot interativos com o plotly.
def plotBoxplot(data, name = '', col = '', target = '', title = '', yaxis = '', xaxis = '', kind = 'normal',
color = ['#8783D1', '#FADF63', '#06D6A0', '#662E9B'], opacity = 0.65, template = 'plotly_white',
orientation = 'v'):
# Realizando as pré-configurações necessárias, para a plotagem do gráfico interativo.
configure_plotly_browser_state()
# Plota gráficos de um ou mais boxplots simples.
if kind == 'normal':
# Plota gráficos verticais.
if orientation == 'v':
# Definindo os dados, a cor, o nome e a transparência que serão utilizados para criar cada um dos Boxplots.
dataTrace = [go.Box(y = data[l], name = l if name == '' else name, marker = {'color': color[2], "opacity": opacity}) for l in data.columns]
# Plota gráficos horizontais.
else:
# Definindo os dados, a cor, o nome e a transparência que serão utilizados para criar cada um dos Boxplots.
dataTrace = [go.Box(x = data[l], name = l if name == '' else name, marker = {'color': color[3], "opacity": opacity}) for l in data.columns]
# Plota gráficos boxplot, para uma variável numérica, agrupada por uma variável categórica.
elif kind == 'groups':
# Captura os registros pertencentes a cada categoria, da variável categórica.
g = [data[data[target] == cat] for cat in data[target].cat.categories]
# Converte a primeira letra do nome de cada categoria para maiúscula.
name = [n.capitalize() for n in data[target].cat.categories]
# Plota gráficos verticais.
if orientation == 'v':
# Definindo os dados, a cor, o nome e a transparência que serão utilizados para criar cada um dos Boxplots.
dataTrace = [go.Box(y = g[l][col], name = name[l], marker = {'color': color[l], "opacity": opacity}) for l in range(0, len(g))]
# Plota gráficos horizontais.
else:
# Definindo os dados, a cor, o nome e a transparência que serão utilizados para criar cada um dos Boxplots.
dataTrace = [go.Box(x = g[l][col], name = name[l], marker = {'color': color[l], "opacity": opacity}) for l in range(0, len(g))]
# Defindo as configurações de layout.
layout = go.Layout (
title = title,
yaxis = {'title': yaxis},
xaxis = {'title': xaxis},
template = template
)
# Criando uma Figure, com os dados e o layout defindos.
fig = go.Figure(data = dataTrace, layout = layout)
# Plotando o Figure com o pyplot.
py.iplot(fig)
# Definindo uma função, para criar Histogramas interativos com o plotly.
def plotHist(data, col = '', target = '', title = '', yaxis = '', xaxis = '',
groups = False, color = ['#8783D1', '#FADF63', '#EF476F'], opacity = 0.65,
template = 'plotly_white'):
# Realizando as pré-configurações necessárias, para a plotagem do gráfico interativo.
configure_plotly_browser_state()
# Criando um histograma para um conjunto de dados.
if groups == False:
# Definindo os dados, a cor, e a transparência que serão utilizados para criar o Histograma.
dataTrace = go.Histogram(x = data, marker = {'color': color[2], "opacity": opacity})
# Criando um histograma para um conjunto de dados agrupado por categorias.
else:
# Captura os registros pertencentes a cada categoria, da variável categórica.
g = [data[data[target] == cat] for cat in data[target].cat.categories]
# Definindo os dados, a cor, e a transparência que serão utilizados para criar cada um dos Histogramas.
dataTrace = [go.Histogram(x = g[cat][col], name = data[target].cat.categories[cat].capitalize(), marker = {'color': color[cat], "opacity": opacity}) for cat in range(0,len(g))]
# Defindo as configurações de layout.
layout = go.Layout(
title = title,
yaxis = {'title': yaxis},
xaxis = {'title': xaxis},
bargap = 0.05,
template = template
)
# Criando uma Figure, com os dados e o layout defindos.
fig = go.Figure(data = dataTrace, layout = layout)
# Plotando o Figure com o pyplot.
py.iplot(fig)
# Definindo uma função, para criar gráficos de Densidade interativos com o plotly.
def plotDensity(data, col = '', target = '', title = '', xaxis = '', group = False,
yaxis = 'Densidade', color = ['#8783D1', '#FADF63', '#3AAED8'],
template = 'plotly_white'):
# Realizando as pré-configurações necessárias, para a plotagem do gráfico interativo.
configure_plotly_browser_state()
# Criando um gráfico de Densidade para o conjunto de dados.
if group == False:
# Definindo os dados, a cor, e os labels que serão utilizados para criar o gráfico de Densidade.
fig = ff.create_distplot([data], group_labels = [xaxis], colors = [color[2]], show_hist = False, show_rug = False)
# Criando um gráfico de Densidade para o conjunto de dados agrupado por categorias.
else:
# Captura os registros pertencentes a cada categoria, da variável categórica.
g = [data[data[target] == cat][col] for cat in data[target].cat.categories]
# Definindo os dados, a cor, e os labels que serão utilizados para criar cada um dos gráficos de Densidade.
fig = ff.create_distplot(g, group_labels = [n.capitalize() for n in data[target].cat.categories], colors = color, show_hist = False, show_rug = False)
# Defindo as configurações de layout.
fig.update_layout (
title_text = title,
yaxis = {"title_text": yaxis},
xaxis = {"title_text": xaxis},
template = template
)
# Plotando o Figure com o pyplot.
fig.show()
Os gráficos de comparação são usados para comparar um ou mais conjuntos de dados. Eles podem comparar itens ou mostrar diferenças ao longo do tempo.
# Definindo uma função, para criar gráficos de Barra interativos com o plotly.
def plotBar(data, col = '', target = '', title = '', yaxis = '', xaxis = '', kind = 'normal',
color = ['#8783D1', '#FADF63', '#FF9F43', '#EE6352', '#FC7A1E'], opacity = 0.65,
template = 'plotly_white', orientation = 'v'):
# Realizando as pré-configurações necessárias para a plotagem do gráfico interativo.
configure_plotly_browser_state()
# Criando gráficos na vertical.
if orientation == 'v':
# Plotando gráfico de barras simples.
if kind == 'normal':
# Definindo os dados, a cor, orientação e a transparência que serão utilizados para criar as barras.
dataTrace = go.Bar(x = data.index, y = data.values, marker = {'color': color[2], "opacity": opacity}, orientation = orientation)
# Plotando gráfico de barras agrupado por uma variável categórica.
elif kind == 'groups':
# Captura os registros pertencentes a cada categoria, da variável categórica.
g = [data[data[target] == cat] for cat in data[target].cat.categories]
# Definindo os dados, a cor, orientação e a transparência que serão utilizados para criar as barras.
dataTrace = [go.Bar(x = g[cat][col], y = g[cat]['count'], name = data[target].cat.categories[cat].capitalize(),
marker = {'color': color[cat], "opacity": opacity}, orientation = orientation) for cat in range(0,len(g))]
# Criando gráficos na horizontal.
else:
# Plotando gráfico de barras simples.
if kind == 'normal':
# Definindo os dados, a cor, orientação e a transparência que serão utilizados para criar as barras.
dataTrace = go.Bar(x = data.values, y = data.index, marker = {'color': color[3], "opacity": opacity}, orientation = orientation)
# Plotando gráfico de barras agrupado por uma variável categórica.
elif kind == 'groups':
# Captura os registros pertencentes a cada categoria, da variável categórica.
g = [data[data[target] == cat] for cat in data[target].cat.categories]
# Definindo os dados, a cor, orientação e a transparência que serão utilizados para criar as barras.
dataTrace = [go.Bar(x = g[cat]['count'], y = g[cat][col], name = data[target].cat.categories[cat].capitalize(),
marker = {'color': color[cat], "opacity": opacity}, orientation = orientation) for cat in range(0,len(g))]
# Defindo as configurações de layout.
layout = go.Layout(
title = title,
yaxis = {'title': yaxis},
xaxis = {'title': xaxis},
template = template
)
# Criando uma Figure, com os dados e o layout defindos.
fig = go.Figure(data = dataTrace, layout = layout)
# Definindo que as barras devem ser dispostas uma ao lado da outra caso estejam agrupadas por categoria.
# Para criar Stacked Bars, utilize: 'stack'.
fig.update_layout(barmode = 'group')
# Plotando o Figure com o pyplot.
fig.show()
Os gráficos de composição são usados para exibir partes de um todo e mudar ao longo do tempo.
# Definindo uma função, para realizar a plotagem de gráficos de pizza.
def plotPie(data, title = ''):
# Realizando as pré-configurações necessárias, para a plotagem do gráfico interativo.
configure_plotly_browser_state()
# Defindo as configurações de layout.
layout = go.Layout (
title = title
)
# Criando uma Figure, com os dados e o layout defindos.
fig = go.Figure (
data = [go.Pie(labels = [i[0].upper() + i[1:] for i in dataCounts.index], values = dataCounts.values, hole = .1)],
layout = layout
)
# Adicionando uma borda branca em cada uma das fatias da pizza.
fig.update_traces (
marker = dict (
line = dict (
color = '#FFFFFF',
width = 1
)
)
)
# Plotando a Figure com o pyplot.
fig.show()
Criaremos uma função, para padronizar as estatísticas que calcularemos, em cada uma das variáveis a serem estudadas.
# Definindo uma função, para gerar um dataframe, com as estatísticas de uma variável do dataset.
def varStats(col, data, target = '', nRows = 10):
# Verificando se a variável é categórica.
if not data[col].dtypes.name in ['object', 'category']:
if target == '':
# Criando um dataframe, com as estatísticas da variável especificada.
stats = pd.DataFrame({
'min' : data[col].min(),
'Q1' : data[col].quantile(.25),
'Median': data[col].median(),
'Mean' : data[col].mean(),
'Q3' : data[col].quantile(.75),
'SD' : data[col].std(),
'Sk' : skew(data[col]),
'Ck' : kurtosis(data[col])
}, index = [col])
else:
# Criando um dataframe, com as estatísticas da variável especificada, agrupada pela variável target.
stats = pd.concat([
data[[col, target]].groupby(target).min(),
data[[col, target]].groupby(target).quantile(.25),
data[[col, target]].groupby(target).median(),
data[[col, target]].groupby(target).mean(),
data[[col, target]].groupby(target).quantile(.75),
data[[col, target]].groupby(target).std(),
data[[col, target]].groupby(target).skew(),
data[[col, target]].groupby(target).apply(lambda group: kurtosis(group)[0])
], axis = 1)
# Renomeando as colunas do DataFrame.
stats.columns = ['min', 'Q1', 'Median', 'Mean', 'Q3', 'SD', 'Sk', 'Ck']
else:
# Criando uma cópia do conjunto de dados.
stats = data.copy()
# Capturando o número de registros do conjunto de dados.
numRows = data.shape[0]
# Criando uma coluna para contabilizar o número de registros em cada um dos grupos.
stats['n'] = 1
# Agrupando os registros a partir da variável especificada e contabilizando o número de registros em cada uma.
stats = pd.DataFrame(stats.groupby([col]).count()['n'])
# Ordenando os resultados obtidos em ordem decrescente.
stats = stats.sort_values(by = 'n', ascending = False)
# Calculando a frequência relativa de cada grupo.
stats['prop (%)'] = stats.apply(lambda n: n / numRows * 100)
# Capturando os n primeiros registros do conjunto de dados.
stats = stats.head(nRows)
# Retornando os resultados obtidos.
return stats
O coeficente de Assimetria (Skewness), indica como os dados estão distribuídos, e para interpretar seu resultado podemos olhar a tabela a seguir:
| Índice de Assimetria | Descrição |
|---|---|
| SK ≈ 0 | Os dados são simétricos. Tanto a cauda do lado direito, quanto a do lado esquerdo da função densidade de probabilidade, são iguais; |
| SK < 0 | A assimetria é negativa. A cauda do lado esquerdo da função densidade de probabilidade, é maior que a do lado direito e; |
| SK > 0 | A assimetria é positiva. A cauda do lado direito da função densidade de probabilidade, é maior que a do lado esquerdo. |
O coeficiente de Curtose (Kurtosis), é uma medida que caracteriza o achatamento da curva da função de distribuição, e para interpretar seu resultado, podemos olhar a tabela a seguir:
| Índice de Curtose | Descrição |
|---|---|
| CK ≈ 0 | A distribuição é normal, e é chamada de Curtose Mesocúrtica; |
| CK < 0 | A Cauda é mais leve que a normal. Para um coeficiente de Curtose negativo, tem-se uma Curtose Platicúrtica e; |
| CK > 0 | A Cauda é mais pesada que a normal. Para um coeficiente de Curtose positivo, tem-se uma Curtose Leptocúrtica. |
# Definindo método para extrair outliers de um conjunto de dados.
def extractOutliers(col, data):
# Caculando os valores do primeiro e terceiro quartil do conjunto de dados.
Q1, Q3 = data[col].quantile(.25), data[col].quantile(.75)
# Calculando o intervalo interquartílico.
IQR = Q3 - Q1
# Calculando os limite inferior e o superior do conjunto de dados.
minLimit, maxLimit = Q1 - 1.5 * IQR, Q3 + 1.5 * IQR
# Segmentando o dataframe em um conjunto de dados sem os outliers e outro só com outliers.
clean, outliers = data[(data[col] > minLimit) & (data[col] < maxLimit)], data[(data[col] < minLimit) | (data[col] > maxLimit)]
# Retornando os dataframes gerados.
return clean, outliers
# Definindo o nome da variável a ser analisada.
col = 'neighbourhood'
# Definindo a descrição da variável nos gráficos.
label = 'Frequência Absoluta'
# Contabilizando a frequência absoluta de cada categoria presente na variável especificada.
dataCounts = data[col].value_counts()
# Plotando um gráfico de barras para as variáveis especificadas.
plotBar (
data = dataCounts,
title = 'Frequência absoluta das categorias da Feature ' + col,
yaxis = label,
orientation = 'v'
)
# Calculando algumas estatísticas para a variável especificada.
varStats(col = col, data = data)
O local mais frequentes é Copacabana aparecendo em 28.89% dos registros do conjunto de dados.
# Definindo o nome da variável a ser analisada.
col = 'room_type'
# Definindo a descrição da variável nos gráficos.
label = 'Frequência Absoluta'
# Contabilizando a frequência absoluta de cada categoria presente na variável especificada.
dataCounts = data[col].value_counts()
# Plotando um gráfico de barras para as variáveis especificadas.
plotBar (
data = dataCounts,
title = 'Frequência absoluta das categorias da Feature ' + col,
yaxis = label,
orientation = 'v'
)
# Plotando um gráfico de pizza para a variável especificada.
plotPie (
data = dataCounts,
title = 'Frequência relativa das categorias da feature ' + col
)
# Calculando algumas estatísticas para a variável especificada.
varStats(col = col, data = data)
A proporção de casas ou apartamentos alugados é abrange 72.4% dos registros, em seguida encontramos quartos privados com 24.9%. Para o processo de modelagem preditiva, o conjunto de dados está desbalanceado.
# Definindo o nome da variável a ser analisada.
col = 'price'
# Definindo a descrição da variável nos gráficos.
label = 'Price'
# Contabilizando a frequência absoluta de cada categoria presente na variável especificada.
dataCounts = data[col].value_counts()
# Plotando um gráfico de histograma para a variável especificada.
plotHist (
data = data[col],
title = 'Histograma para a variável ' + col,
xaxis = label,
yaxis = 'Frequência Absoluta'
)
# Criando um gráfico de Densidade para a variável especificada.
plotDensity (
data = data[col],
title = 'Gráfico de Densidade para a variável ' + col,
xaxis = label
)
# Plotando um gráfico de boxplot para as variável especificada.
plotBoxplot (
data = data[[col]],
title = 'Boxplot para a variável ' + col,
xaxis = 'Variável',
name = label
)
Há um outlier que está distorcento drasticamente a distribuição do conjunto de dados dos preços. Vamos identificá-lo:
# Capturando os registros que contém o maior valor do conjunto de dados para a variável especificada.
data[data[col] == data[col].max()]
# Calculando algumas estatísticas para a variável especificada.
varStats(col, data = data)
Destacamos que:
# Definindo o nome da variável a ser analisada.
col = 'minimum_nights'
# Definindo a descrição da variável nos gráficos.
label = 'Frequência Absoluta'
# Contabilizando a frequência absoluta de cada categoria presente na variável especificada.
dataCounts = data[col].value_counts()
# Plotando um gráfico de barras para as variáveis especificadas.
plotBar (
data = dataCounts,
title = 'Frequência absoluta das categorias da Feature ' + col,
yaxis = label,
orientation = 'h'
)
# Plotando um gráfico de boxplot para as variável especificada.
plotBoxplot (
data = data[[col]],
title = 'Boxplot para a variável ' + col,
xaxis = 'Variável',
name = label
)
Há um outlier que está distorcento drasticamente a distribuição do conjunto de dados dos preços. Vamos identificá-lo:
# Capturando os registros que contém o maior valor do conjunto de dados para a variável especificada.
data[data[col] == data[col].max()]
# Calculando algumas estatísticas para a variável especificada.
varStats(col, data = data)
Destacamos que:
# Definindo o nome da variável a ser analisada.
col = 'number_of_reviews'
# Definindo a descrição da variável nos gráficos.
label = 'Frequência Absoluta'
# Contabilizando a frequência absoluta de cada categoria presente na variável especificada.
dataCounts = data[col].value_counts()
# Plotando um gráfico de barras para as variáveis especificadas.
plotBar (
data = dataCounts,
title = 'Frequência absoluta das categorias da Feature ' + col,
yaxis = label,
orientation = 'h'
)
# Plotando um gráfico de boxplot para as variável especificada.
plotBoxplot (
data = data[[col]],
title = 'Boxplot para a variável ' + col,
xaxis = 'Variável',
name = label
)
# Calculando algumas estatísticas para a variável especificada.
varStats(col, data = data)
Destacamos que:
# Definindo o nome da variável a ser analisada.
col = 'reviews_per_month'
# Definindo a descrição da variável nos gráficos.
label = 'Frequência Absoluta'
# Contabilizando a frequência absoluta de cada categoria presente na variável especificada.
dataCounts = data[col].value_counts()
# Plotando um gráfico de barras para as variáveis especificadas.
plotBar (
data = dataCounts,
title = 'Frequência absoluta das categorias da Feature ' + col,
yaxis = label,
orientation = 'h'
)
# Plotando um gráfico de boxplot para as variável especificada.
plotBoxplot (
data = data[[col]],
title = 'Boxplot para a variável ' + col,
xaxis = 'Variável',
name = label
)
# Calculando algumas estatísticas para a variável especificada.
varStats(col, data = data)
Destacamos que:
# Definindo o nome da variável a ser analisada.
col = 'calculated_host_listings_count'
# Definindo a descrição da variável nos gráficos.
label = 'Frequência Absoluta'
# Contabilizando a frequência absoluta de cada categoria presente na variável especificada.
dataCounts = data[col].value_counts()
# Plotando um gráfico de barras para as variáveis especificadas.
plotBar (
data = dataCounts,
title = 'Frequência absoluta das categorias da Feature ' + col,
yaxis = label,
#xaxis = 'Frequência Absoluta',
orientation = 'h'
)
# Plotando um gráfico de boxplot para as variável especificada.
plotBoxplot (
data = data[[col]],
title = 'Boxplot para a variável ' + col,
xaxis = 'Variável',
name = label
)
# Calculando algumas estatísticas para a variável especificada.
varStats(col, data = data)
Destacamos que:
# Definindo o nome da variável a ser analisada.
col = 'availability_365'
# Definindo a descrição da variável nos gráficos.
label = 'Frequência Absoluta'
# Contabilizando a frequência absoluta de cada categoria presente na variável especificada.
dataCounts = data[col].value_counts()
# Plotando um gráfico de barras para as variáveis especificadas.
plotBar (
data = dataCounts,
title = 'Frequência absoluta das categorias da Feature ' + col,
yaxis = label,
orientation = 'h'
)
# Plotando um gráfico de boxplot para as variável especificada.
plotBoxplot (
data = data[[col]],
title = 'Boxplot para a variável ' + col,
xaxis = 'Variável',
name = label
)
# Calculando algumas estatísticas para a variável especificada.
varStats(col, data = data)
Destacamos que:
Iremos definir algumas funções, para padronizar as plotagens de gráficos que criaremos.
# Definindo o nome da variável a ser analisada.
col = 'price'
# Extraindo outliers do conjunto de dados da variável especificada.
data, outliers = extractOutliers(col = col, data = data)
# Visualizando os primeiros outliers do conjunto de dados especificado.
outliers.head(10)
# Definindo a descrição da variável nos gráficos.
label = 'Price'
# Contabilizando a frequência absoluta de cada categoria presente na variável especificada.
dataCounts = data[col].value_counts()
# Plotando um gráfico de histograma para a variável especificada.
plotHist (
data = data[col],
title = 'Histograma para a variável ' + col,
xaxis = label,
yaxis = 'Frequência Absoluta'
)
# Criando um gráfico de Densidade para a variável especificada.
plotDensity (
data = data[col],
title = 'Gráfico de Densidade para a variável ' + col,
xaxis = label
)
# Plotando um gráfico de boxplot para as variável especificada.
plotBoxplot (
data = data[[col]],
title = 'Boxplot para a variável ' + col,
xaxis = 'Variável',
name = label
)
Mesmo com a extração dos outliers, a distorção foi amenizada mas não eliminada, e por isso a assimetria do conjunto de dados continua alta.
# Calculando algumas estatísticas para a variável especificada.
varStats(col, data = data)
Destacamos que:
# Definindo o nome da variável a ser analisada.
col = 'minimum_nights'
# Extraindo outliers do conjunto de dados da variável especificada.
data, outliers = extractOutliers(col = col, data = data)
# Visualizando os primeiros outliers do conjunto de dados especificado.
outliers.head(10)
# Definindo a descrição da variável nos gráficos.
label = 'Frequência Absoluta'
# Contabilizando a frequência absoluta de cada categoria presente na variável especificada.
dataCounts = data[col].value_counts()
# Plotando um gráfico de barras para as variáveis especificadas.
plotBar (
data = dataCounts,
title = 'Frequência absoluta das categorias da Feature ' + col,
yaxis = label,
orientation = 'h'
)
# Plotando um gráfico de boxplot para as variável especificada.
plotBoxplot (
data = data[[col]],
title = 'Boxplot para a variável ' + col,
xaxis = 'Variável',
name = label
)
Após a remoção dos outliers, a distribuição do conjunto de dados se tornou mais clara.
# Calculando algumas estatísticas para a variável especificada.
varStats(col, data = data)
Destacamos que:
# Definindo o nome da variável a ser analisada.
col = 'number_of_reviews'
# Extraindo outliers do conjunto de dados da variável especificada.
data, outliers = extractOutliers(col = col, data = data)
# Visualizando os primeiros outliers do conjunto de dados especificado.
outliers.head(10)
# Definindo a descrição da variável nos gráficos.
label = 'Frequência Absoluta'
# Contabilizando a frequência absoluta de cada categoria presente na variável especificada.
dataCounts = data[col].value_counts()
# Plotando um gráfico de barras para as variáveis especificadas.
plotBar (
data = dataCounts,
title = 'Frequência absoluta das categorias da Feature ' + col,
yaxis = label,
orientation = 'h'
)
# Plotando um gráfico de boxplot para as variável especificada.
plotBoxplot (
data = data[[col]],
title = 'Boxplot para a variável ' + col,
xaxis = 'Variável',
name = label
)
Mesmo com a extração dos outliers, a distorção foi amenizada mas não eliminada, e por isso a assimetria do conjunto de dados continua alta.
# Calculando algumas estatísticas para a variável especificada.
varStats(col, data = data)
Destacamos que:
# Definindo o nome da variável a ser analisada.
col = 'reviews_per_month'
# Extraindo outliers do conjunto de dados da variável especificada.
data, outliers = extractOutliers(col = col, data = data)
# Visualizando os primeiros outliers do conjunto de dados especificado.
outliers.head(10)
# Definindo a descrição da variável nos gráficos.
label = 'Frequência Absoluta'
# Contabilizando a frequência absoluta de cada categoria presente na variável especificada.
dataCounts = data[col].value_counts()
# Plotando um gráfico de barras para as variáveis especificadas.
plotBar (
data = dataCounts,
title = 'Frequência absoluta das categorias da Feature ' + col,
yaxis = label,
orientation = 'h'
)
# Plotando um gráfico de boxplot para as variável especificada.
plotBoxplot (
data = data[[col]],
title = 'Boxplot para a variável ' + col,
xaxis = 'Variável',
name = label
)
Mesmo com a extração dos outliers, a distorção foi amenizada mas não eliminada, e por isso a assimetria do conjunto de dados continua alta.
# Calculando algumas estatísticas para a variável especificada.
varStats(col, data = data)
Destacamos que:
# Definindo o nome da variável a ser analisada.
col = 'calculated_host_listings_count'
# Extraindo outliers do conjunto de dados da variável especificada.
data, outliers = extractOutliers(col = col, data = data)
# Visualizando os primeiros outliers do conjunto de dados especificado.
outliers.head(10)
# Definindo a descrição da variável nos gráficos.
label = 'Frequência Absoluta'
# Contabilizando a frequência absoluta de cada categoria presente na variável especificada.
dataCounts = data[col].value_counts()
# Plotando um gráfico de barras para as variáveis especificadas.
plotBar (
data = dataCounts,
title = 'Frequência absoluta das categorias da Feature ' + col,
yaxis = label,
orientation = 'h'
)
# Plotando um gráfico de boxplot para as variável especificada.
plotBoxplot (
data = data[[col]],
title = 'Boxplot para a variável ' + col,
xaxis = 'Variável',
name = label
)
Mesmo com a extração dos outliers, a distorção foi amenizada mas não eliminada, e por isso a assimetria do conjunto de dados continua alta.
# Calculando algumas estatísticas para a variável especificada.
varStats(col, data = data)
Destacamos que:
# Adicionando dados sem outliers a linhagem do conjunto de dados
allData['withoutOutliers'] = data.copy()
# Definindo uma função para para aplicar as transformações MimMaxScaler, StandardScaler,
# Yeo-Johnson e Normalize as features de um conjunto de dados de treino e de teste.
def dataTransform(train, test, transform = 'MM'):
# Criando cópias dos DataFrames.
trainFeatures = train.copy()
testFeatures = test.copy()
# Criando um variável para identificar os dados de treino e de teste.
trainFeatures['train'] = 1
testFeatures['train'] = 0
# Unindo dados de treino e de teste em um único conjunto de dados.
features = pd.concat([trainFeatures, testFeatures])
# Capturando a variável que identifica os dados de treino e de teste.
train = features['train']
# Eliminando a variável de identificação do Dataframe.
features = features.drop('train', axis = 1)
# Criando variável para armazenar o conjunto de dados transformado.
featuresTransformed = None
# Aplicando a transformação selecionada.
if transform == 'MM':
# Criando um objeto da classe MinMaxScaler().
scaler = MinMaxScaler()
# Aplicando a escala nas Features e capturando o resultado obtido.
featuresTransformed = scaler.fit_transform(features)
# Criando um DataFrame com os resultados obtidos.
featuresTransformed = pd.DataFrame(data = featuresTransformed, columns = features.columns)
elif transform == 'SS':
# Criando um objeto da classe StandardScaler().
scaler = StandardScaler()
# Aplicando a escala nas Features e capturando o resultado obtido.
featuresTransformed = scaler.fit_transform(features)
# Criando um DataFrame com os resultados obtidos.
featuresTransformed = pd.DataFrame(data = featuresTransformed, columns = features.columns)
elif transform == 'ND':
# Criando um objeto da classe StandardScaler().
scaler = StandardScaler()
# Aplicando a escala nas Features e capturando o resultado obtido.
featuresTransformed = scaler.fit_transform(features)
# Criando um DataFrame com os resultados obtidos.
featuresTransformed = pd.DataFrame(data = featuresTransformed, columns = features.columns)
# Criando um objeto da classe PowerTransformer().
scaler = PowerTransformer(method = 'yeo-johnson', standardize = False)
# Aplicando a escala nas Features e capturando o resultado obtido.
featuresTransformed = scaler.fit_transform(featuresTransformed)
# Criando um DataFrame com os resultados obtidos.
featuresTransformed = pd.DataFrame(data = featuresTransformed, columns = features.columns)
elif transform == 'N':
# Normalizando cada feature para uma unidade uniforme (vetor unitário).
featuresTransformed = normalize(features, axis = 0)
# Criando um DataFrame com os resultados obtidos.
featuresTransformed = pd.DataFrame(data = featuresTransformed, columns = features.columns)
# Atribuindo variável identificadora ao DataFrame transformado.
featuresTransformed['train'] = train.values
# Separando dados de treino e de teste transformados.
trFeatures = featuresTransformed[featuresTransformed['train'] == 1].drop('train', axis = 1)
tstFeatures = featuresTransformed[featuresTransformed['train'] == 0].drop('train', axis = 1)
# Retornando dados de treino e teste transformados.
return trFeatures, tstFeatures
# Definindo função para aplicar a técnica PCA a um conjunto de dados de treino e teste.
def pcaTransform(train, test, nComponents = 8):
# Criando cópias dos DataFrames.
trainFeatures = train.copy()
testFeatures = test.copy()
# Criando um variável para identificar os dados de treino e de teste.
trainFeatures['train'] = 1
testFeatures['train'] = 0
# Unindo dados de treino e de teste em um único conjunto de dados.
features = pd.concat([trainFeatures, testFeatures])
# Capturando a variável que identifica os dados de treino e de teste.
train = features['train']
# Eliminado a variável de identificação do Dataframe.
features = features.drop('train', axis = 1)
# Criando variável para armazenar o conjunto de dados transformados.
featuresTransformed = None
# Normalizando cada feature para uma unidade uniforme (vetor unitário).
featuresTransformed = normalize(features, axis = 0)
# Instanciando um objeto da classe PCA para criar os componentes.
pca = PCA(n_components = nComponents)
# Capturando os componentes.
featuresTransformed = pca.fit_transform(featuresTransformed)
# Criando um DataFrame com os resultados obtidos.
featuresTransformed = pd.DataFrame(data = featuresTransformed, columns = ['PCA_' + str(i) for i in range(0, nComponents)])
# Atribuindo variável identificadora ao DataFrame transformado.
featuresTransformed['train'] = train.values
# Separando dados de treino e de teste transformados.
trFeatures = featuresTransformed[featuresTransformed['train'] == 1].drop('train', axis = 1)
tstFeatures = featuresTransformed[featuresTransformed['train'] == 0].drop('train', axis = 1)
# Retornando dados de treino e teste transformados.
return trFeatures, tstFeatures
Nesta etapa, iremos segmentar os registros em dados de treino e de teste. Mas, primeiro iremos criar diferentes conjuntos de dados como base no dataset original.
# Criando conjunto de dados como a coluna positions original.
allData['position'] = allData['raw'].drop(['id', 'host_id', 'neighbourhood_group', 'last_review', 'name', 'host_name'], axis = 1)
# Criando conjunto de dados como a coluna positions sem outliers.
allData['posWithoutNa'] = allData['raw'].drop(['id', 'host_id', 'neighbourhood_group', 'last_review', 'name', 'host_name'], axis = 1).dropna()
# Criando conjunto de dados sem valores nulos.
allData['posWithNa'] = allData['raw'].drop(['id', 'host_id', 'neighbourhood_group', 'last_review', 'name', 'host_name'], axis = 1)
# Criando conjunto de dados sem valores nulos e sem a coluna host_name.
allData['posWithoutLNa'] = allData['raw'].drop(['id', 'host_id', 'neighbourhood_group', 'last_review', 'name'], axis = 1).dropna()
# Criando conjunto de dados sem a coluna reviews_per_month.
allData['withoutRevPerMonth'] = allData['raw'].drop(['id', 'host_id', 'neighbourhood_group', 'last_review', 'name', 'host_name', 'reviews_per_month'], axis = 1)
# Varrendo duas versões do conjunto de dados dentro do conjunto de linhagem.
for cl in ['posWithoutNa', 'posWithNa']:
# Capturando o conjunto de dados especificado.
dt = allData[cl]
# Iterando cada um dos nomes das variáveis especificadas.
for columns in dt.columns:
# Convertendo as variáveis especificadas em valores numéricos.
if columns in ['last_review','host_name', 'neighbourhood', 'room_type']:
# Convertendo o tipo de dados especificado para o tipo de dado categórico.
dt[columns] = dt[columns].astype('category')
# Capturando os valores numéricos das variáveis especificadas.
dt[columns] = dt[columns].cat.codes
# Adicionando a versão atualizada do conjunto de dados na lista de linhagem.
allData[cl] = dt
# Capturando o conjunto de dados com valores nulo.
dt = allData['posWithNa'].copy()
# Iterando o nome das colunas do conjunto de dados.
for col in [i for i in dt.columns if i != 'room_type']:
# Capturando o valor mínimo e máximo do conjunto de dados.
vMin, vMax = dt[col].min(), dt[col].max()
# Normalizando o conjunto de dados da variável especificada.
dt[col] = [(i - vMin) / (vMax - vMin) if not np.isnan(i) else i for i in dt[col]]
# Adicionando o conjunto de dados escalado com dados nulos presentes.
allData['posWithNaMM'] = dt
# Definindo o conjunto de dados, dentro da linhagem, que será utilizado para gerar os modelos de machine learning.
data = allData['posWithoutNa'].copy()
Iremos definir 80% do conjunto de dados para treino e 20% para teste.
# Criando conjunto de dados de treino e de teste.
trainFeatures, testFeatures, trainTarget, testTarget = train_test_split(data.drop('room_type', axis = 1), data['room_type'], test_size = 0.20)
# Verificando as novas dimensões do DataFrame de treino.
trainFeatures.shape
# Verificando as novas dimensões do DataFrame de teste.
testFeatures.shape
Iremos aplicar diferentes transformações, nas variáveis preditoras dos conjuntos de dados de treino e de teste.
# Aplicando a transformação MinMaxScaler, as Features do conjunto de dados de treino e de teste.
trainFeaturesMM, testFeaturesMM = dataTransform (
train = trainFeatures,
test = testFeatures,
transform = 'MM'
)
# Aplicando a transformação StandardScaler, as Features do conjunto de dados de treino e de teste.
trainFeaturesSS, testFeaturesSS = dataTransform (
train = trainFeatures,
test = testFeatures,
transform = 'SS'
)
# Aplicando a transformação Yeo-Johnson, as Features do conjunto de dados de treino e de teste.
trainFeaturesNormDistribuition, testFeaturesNormDistribuition = dataTransform (
train = trainFeatures,
test = testFeatures,
transform = 'ND'
)
# Aplicando a transformação Normalize, as Features do conjunto de dados de treino e de teste.
trainFeaturesNormalized, testFeaturesNormalized = dataTransform (
train = trainFeatures,
test = testFeatures,
transform = 'N'
)
Aplicaremos diferentes técnicas de Feature Selection, para determinar qual é a melhor combinação de variáveis preditoras a ser utilizada.
Este método seleciona recursos de acordo com as k pontuações mais altas.
# Definindo qual conjunto de dados, já escalado, deve ser utilizado.
tFeatures = trainFeaturesMM
# Instanciando um objeto da classe SelectKBest, para selecionar as melhores variáveis preditoras.
skb = SelectKBest(chi2, k = tFeatures.shape[1])
# Capturando os scores das variáveis preditoras.
bestFeatuesSKB = skb.fit_transform(tFeatures, trainTarget)
# Capturando o nome das variáveis preditoras.
bfSkb = tFeatures.columns[skb.get_support()]
# Exibindo o nome das variáveis preditoras.
bfSkb
# Criando um DataFrame, com os scores obtidos para cada uma das Features, segundo a técnica utilizada.
sc = pd.Series(skb.scores_, index = tFeatures.columns)
# Capturando os scores das variáveis preditoras.
sc = sc[skb.get_support()]
# Ordenando o Dataframe com os scores.
sc = sc.sort_values(ascending = False)
# Plotando um gráfico de barras, dos scores gerados para as features, a partir da técnica utilizada.
plotBar (
data = sc,
title = 'Scores das melhores features com o SelectKBest',
yaxis = 'Features',
xaxis = 'Scores',
orientation = 'h'
)
Segundo o método Select K Best, as variáveis availability_365, neighbourhood e number_of_reviews são as mais importantes.
O Information gain ou Mutual information mede quanta informação a presença / ausência de um recurso contribui para fazer a previsão correta da variável target.
# Definindo qual conjunto de dados, já escalado, deve ser utilizado.
tFeatures = trainFeaturesMM
# Instanciando um objeto da classe mutual_info_classif.
bestFeatuesIG = mutual_info_classif(tFeatures, trainTarget, discrete_features = 'auto', n_neighbors = 3)
# Inserindo Scores obtidos em uma Série temporal.
scoreFeatures = pd.Series(bestFeatuesIG, index = tFeatures.columns)
# Capturando os scores das variáveis preditoras em ordem decrescente.
bfIg = scoreFeatures.sort_values(ascending = False)
# Plotando um gráfico de barras, dos scores gerados para as features, a partir da técnica utilizada.
plotBar (
data = bfIg,
title = 'Scores das melhores features com o Information Gain',
yaxis = 'Features',
xaxis = 'Scores',
orientation = 'h'
)
Segundo o método Information Gain, as variáveis price, minimum_nights e neighbourhood são as mais importantes.
# Capturando o nome das variáveis preditoras.
bfIg = bfIg.index
# Exibindo o nome das variáveis preditoras.
bfIg
Se os recursos forem categóricos, calcularemos uma estatística qui-quadrado entre cada recurso e a variável target. No entanto, se os recursos forem quantitativos, calcularemos a ANOVA F-Value entre cada recurso e a variável target.
As pontuações do F-Value examinam se, quando agrupamos a característica numérica pela variável target, as médias para cada grupo se tornam significativamente diferentes.
# Definindo qual conjunto de dados, já escalado, deve ser utilizado.
tFeatures = trainFeaturesMM
# Instanciando um objeto da classe SelectKBest para selecionar as melhores variáveis preditoras a partir dos scores ANOVA F-Values.
skb = SelectKBest(f_classif, k = tFeatures.shape[1])
# Capturando as variáveis preditoras.
bestFeatuesANOVA = skb.fit_transform(tFeatures, trainTarget)
# Capturando o nome das variáveis preditoras.
bfAnova = tFeatures.columns[skb.get_support()]
# Exibindo o nome das variáveis preditoras.
bfAnova
# Criando uma Série Temporal com os scores obtidos para cada uma das Features segundo a técnica utilizada.
sc = pd.Series(skb.scores_, index = tFeatures.columns)
# Capturando os scores das variáveis preditoras.
sc = sc[skb.get_support()]
# Ordenando a Série Temporal em ordem decrescente dos scores.
sc = sc.sort_values(ascending = False)
# Plotando um gráfico de barras, dos scores gerados para as features, a partir da técnica utilizada.
plotBar (
data = sc,
title = 'Scores das melhores features com o ANOVA F-value',
yaxis = 'Features',
xaxis = 'Scores',
orientation = 'h'
)
Segundo o método ANOVA F-Value, as variáveis latitude, reviews_per_month e neighbourhood são as mais importantes.
O Forward Selection é um método iterativo, no qual começamos sem ter nenhum recurso no modelo. A cada iteração, adicionamos uma variável que melhora o modelo e efetuamos este procedimento até que a performance do modelo pare de evoluir.
A seleção de recursos começa avaliando todas as variáveis individualmente, e seleciona aquela que gera o algoritmo com o melhor desempenho, de acordo com um critério de avaliação predefinido. Em seguida, se avalia todas as combinações possíveis das variáveis já selecionadas e dos recursos ainda não escolhidos para definir a combinação que produz o algoritmo com a melhor performance, com base nos mesmos critérios predefinidos.
# Definindo qual conjunto de dados, já escalado, deve ser utilizado.
tFeatures = trainFeaturesMM
# Instanciando um objeto da classe SFS para selecionar as melhores variáveis preditoras segundo sua acurácia, utilizando o algoritmo XGBClassifer.
sfs = SFS (
estimator = xgb.XGBClassifier(),
k_features = tFeatures.shape[1],
forward = True,
floating = False,
verbose = 2,
scoring = 'accuracy',
cv = 3
)
# Capturando as variáveis preditoras.
sfs = sfs.fit(
X = tFeatures,
y = trainTarget
)
# Capturando o nome das variáveis preditoras.
bfSfs = tFeatures.columns[list(sfs.k_feature_idx_)]
# Exibindo o nome das variáveis preditoras.
bfSfs
# Capturando os resultados obtidos pela Técnica Forward Selection.
sc = pd.DataFrame(sfs.get_metric_dict())
# Capturando os scores e o nome das Features, gerados a cada busca.
sc = sc.loc[['cv_scores', 'feature_names'], :].transpose()
# Capturando o nome das features utilizadas em cada avaliação.
featureNames = sc.feature_names
# Criando índices com o número de Features utilizadas em cada avaliação.
columns = [str(i) + ' Feature' if i == 1 else str(i) + ' Features' for i in range(1, sc.shape[0] + 1)]
# Remodelando os dados do DataFrame para serem plotados.
fs = pd.DataFrame()
for i in range(1, sc.shape[0] + 1):
# Atribui os primeiros scores ao DataFrame, caso esteja vazio.
if sc.empty:
fs = pd.DataFrame(sc['cv_scores'][i], columns = [columns[i - 1]])
else:
fs[columns[i - 1]] = sc['cv_scores'][i]
# Plotando os scores da acurácia, obtida pelas features selecionadas em cada fase de busca, segundo a técnica Forward Selection.
plotBoxplot (
data = fs,
title = 'Acurácia das melhores Features encontradas pelo técnica Forward Selection',
xaxis = 'Features selecionadas'
)
# Transpondo DataFrame.
fs = fs.transpose()
# Criando uma nova coluna, com os nomes das Features utilizadas, em cada avaliação no DataFrame.
fs['featuresNames'] = [', '.join(f) for f in featureNames]
# Exibindo o nome das features utilizadas em cada avaliação.
fs[['featuresNames']]
O uso das 9 variáveis selecionadas gera os menores scores para a métrica Log Loss.
O Extremely Randomized Trees Classifier (Extra Trees Classifier) é um tipo de técnica de aprendizagem de conjunto que agrega os resultados de várias árvores de decisão descorrelacionadas coletadas em uma “floresta” para produzir seu resultado de classificação. Em conceito, é muito semelhante a um Classificador Random Forest e só difere na forma de construção das árvores de decisão na floresta.
Cada árvore de decisão na floresta de árvores extras é construída a partir da amostra de treinamento original. Então, em cada nó de teste, cada árvore é fornecida com uma amostra aleatória de k recursos do conjunto de recursos a partir do qual cada árvore de decisão deve selecionar o melhor recurso para dividir os dados com base em alguns critérios matemáticos (normalmente o índice de Gini). Essa amostra aleatória de recursos leva à criação de várias árvores de decisão não correlacionadas.
Para realizar a seleção de características usando a estrutura de floresta acima, durante a construção da floresta, para cada característica, a redução total normalizada nos critérios matemáticos usados na decisão da característica de divisão (Índice de Gini se o Índice de Gini for usado na construção de floresta) é computado. Esse valor é chamado de Importância Gini do recurso. Para realizar a seleção de recursos, cada recurso é ordenado em ordem decrescente de acordo com a Importância Gini de cada recurso e o usuário seleciona os k principais recursos de acordo com sua escolha.
# Definindo qual conjunto de dados, já escalado, deve ser utilizado.
tFeatures = trainFeaturesMM
# Instanciando um objeto da classe ExtraTreesClassifier.
modelETC = ExtraTreesClassifier()
# Computando os scores de cada feature.
modelETC.fit (
X = tFeatures,
y = trainTarget
)
# Inserindo Scores obtidos em uma Série Temporal.
featuresImpETC = pd.Series(data = modelETC.feature_importances_, index = tFeatures.columns)
# Ordeando o nome das variáveis preditoras segundo seu score em ordem decrescente.
bfEtc = featuresImpETC.sort_values(ascending = False)
# Plotando um gráfico de barras, dos scores gerados para as features, a partir da técnica utilizada.
plotBar (
data = bfEtc,
title = 'Scores das melhores features com o Extra Trees Classifier',
yaxis = 'Features',
xaxis = 'Scores',
orientation = 'h'
)
Segundo o método Extra Trees Classifier, as variáveis price, latitude e longitude são as mais importantes.
# Capturando o nome das variáveis preditoras.
bfEtc = bfEtc.index
# Exibindo o nome das variáveis preditoras.
bfEtc
O Random Forest, é um dos algoritmos de aprendizado de máquina mais populares. É um dos mais bem-sucedidos porque fornece, em geral, um bom desempenho preditivo, baixo overfitting e é de fácil interpretabilidade.
Essa interpretabilidade é dada pela facilidade de se derivar a importância de cada variável na árvore de decisão. Em outras palavras, é fácil calcular o quanto cada variável está contribuindo para a decisão do modelo.
O Random Forest consiste em 4-12 centenas de árvores de decisão, cada uma delas construída sobre uma extração aleatória das observações do conjunto de dados e uma extração aleatória das características. Nem toda árvore vê todas as características ou todas as observações, e isso garante que as árvores sejam descorrelacionadas e, portanto, menos sujeitas a sobreajuste. Cada árvore também é uma sequência de perguntas sim-não com base em um único recurso ou em uma combinação de recursos. Em cada nó (isto é em cada questão), os três dividem o conjunto de dados em 2 depósitos, cada um deles hospedando observações que são mais semelhantes entre si e diferentes das do outro bloco. Portanto, a importância de cada recurso é derivada do quão "puro" cada um dos blocos é.
Para classificação, a medida de impureza é a impureza de Gini ou o ganho / entropia de informação. Para regressão, a medida de impureza é a variância. Portanto, ao treinar uma árvore, é possível calcular o quanto cada recurso diminui a impureza. Quanto maior for a diminuição da impureza que um recurso gerar, mais importante ele será. Em florestas aleatórias, a diminuição da impureza de cada recurso pode ser calculada em média entre as árvores para determinar a importância final da variável.
# Definindo qual conjunto de dados, já escalado, deve ser utilizado.
tFeatures = trainFeaturesMM
# Instanciando um objeto da classe RandomForestClassifier.
rfImp = RandomForestClassifier (
n_estimators = 200,
random_state = 0
)
# Treinando o classificador com o conjunto de dados de treino.
rfImp.fit(
X = tFeatures,
y = trainTarget
)
# Prevendo os scores das features dos dados de treino.
pred = rfImp.predict(tFeatures)
# Convertendo os scores para um DataFrame.
featuresImpRf = pd.Series(data = rfImp.feature_importances_, index = tFeatures.columns)
# Capturando os scores de cada uma das features.
bfRf = featuresImpRf.nlargest(8)
plotBar (
data = bfRf,
title = 'Scores das melhores features com o Random Forest',
yaxis = 'Features',
xaxis = 'Scores',
orientation = 'h'
)
Segundo o método Random Forest, as variáveis price, latitude e longitude são as mais importantes.
# Capturando o nome das variáveis preditoras.
bfRf = bfRf.index
# Exibindo o nome das variáveis preditoras.
bfRf
A Análise de componente principal (Principal Component Analysis - PCA) é uma técnica de redução de dimensionalidade linear que pode ser utilizada para extrair informações de um espaço de alta dimensão projetando-as em um subespaço de dimensão inferior. Ele tenta preservar as partes essenciais que têm mais variação dos dados e remover as partes não essenciais com menos variação. As dimensões nada mais são do que recursos que representam os dados.
Uma coisa importante a se notar sobre o PCA é que é uma técnica de redução de dimensionalidade não supervisionada. Você pode agrupar os pontos de dados semelhantes com base na correlação de recursos entre eles sem qualquer supervisão (ou rótulos).
# Aplicando a técnica PCA, para criar 8 Componentes, a partir dos dados de treino e de teste.
trainFeaturesPCA, testFeaturesPCA = pcaTransform(train = trainFeatures, test = testFeatures, nComponents = 5)
Iremos definir algumas funções, para executar as etapas de modelagem preditiva.
# Definindo uma função, para treinar diferentes algoritmos, e prever a variável Target de um conjunto de dados.
def classifiersTraining(features, tTarget, printMeans = True, scoring = 'accuracy'):
# Definindo os valores do seed e do número de folds.
num_folds = 10
seed = 100
# Criando uma lista, para armazenar os modelos que serão utilizados.
models = []
# Criando Listas para armazenar os resultados e os nomes de cada um dos algoritmos testados.
results = []
names = []
# Criando um Dataframe para armazenar a média e o desvio-padrão de cada um dos algoritmos testados.
means = pd.DataFrame(columns = ['mean', 'std'])
# Adicionando os modelos a lista.
models.append(('LR' , LogisticRegression() ))
models.append(('LDA' , LinearDiscriminantAnalysis() ))
models.append(('QDA' , QuadraticDiscriminantAnalysis() ))
models.append(('RC' , RidgeClassifierCV() ))
models.append(('NB' , GaussianNB() ))
models.append(('KNN' , KNeighborsClassifier() ))
models.append(('CART' , DecisionTreeClassifier() ))
models.append(('AdaBoost', AdaBoostClassifier() ))
models.append(('GB' , GradientBoostingClassifier() ))
models.append(('SVM' , SVC() ))
models.append(('RF' , RandomForestClassifier() ))
models.append(('XGBoost' , xgb.XGBClassifier() ))
# Avaliando cada um dos modelos da lista de modelos.
for name, model in models:
# Instanciando um objeto da classe Kfold para criar os folds.
kfold = KFold(n_splits = num_folds, random_state = seed)
# Treinando o modelo com Cross Validation.
cv_results = cross_val_score(model, features, tTarget, cv = kfold, scoring = scoring)
# Adicionando os resultados gerados na lista de resultados.
results.append(cv_results)
# Adicionando o nome do modelo avaliado na lista de nomes.
names.append(name)
# Adicionando a média e o desvio-padrão, dos resultados gerados pelo modelo analisado, ao Dataframe de médias.
means = means.append (
pd.DataFrame (
data = [[cv_results.mean(), cv_results.std()]],
columns = ['mean', 'std'],
index = [name]
)
)
# Imprime uma mensagem, contendo os resultados obtidos ao fim do treinamento, de cada um dos modelos.
if printMeans:
# Cria a mensagem a ser impressa.
msg = "%s: %f (%f)" % (name, cv_results.mean(), cv_results.std())
# Imprime a mensagem.
print(msg)
# Cria um DataFrame, com os resultados obtidos por cada um dos modelos avaliados.
results = pd.DataFrame(np.transpose(results), columns = names)
# Retorna o DataFrame, com os resultados e com as médias geradas.
return (results, means)
# Definindo uma função para salvar um modelo preditivo já treinado.
def saveModel(name, model, fold = 'content/outputs/', ext = '.sav'):
# Definindo o diretório e o nome do arquivo que será utilizado para salvar o modelo.
dir = fold + name + ext
# Salvando o modelo especificado.
pickle.dump(model, open(dir, 'wb'))
# Imprimindo mensagem de sucesso.
print("Modelo salvo!")
# Definindo uma função para carregar um modelo preditivo já treinado.
def loadModel(name, fold = 'content/outputs/', ext = '.sav'):
# Definindo o diretório e o nome do arquivo que será utilizado para carregar o modelo.
dir = fold + name + ext
# Imprimindo mensagem de sucesso.
print("Modelo carregado!")
# Carregando o modelo especificado.
return pickle.load(open(dir, 'rb'))
# Treinando classificadores, a partir dos componentes criados pela técnica PCA.
resultsPCA = classifiersTraining (
features = trainFeaturesPCA,
tTarget = trainTarget
)
# Plotando os scores, da acurácia dos classificadores treinados, em boxplots.
plotBoxplot(data = resultsPCA[0])
O algoritmo Random Forest, foi o que obteve a melhor acurácia, para o conjunto de componentes do PCA.
# Treinando classificadores, a partir da escala, e da técnica de Feature Selection utilizada.
resultsMM = classifiersTraining (
features = trainFeaturesMM,
tTarget = trainTarget
)
# Plotando os scores, da acurácia dos classificadores treinados, em boxplots.
plotBoxplot(data = resultsMM[0])
O algoritmo XGBoost, foi o que obteve a melhor acurácia, para o conjunto dados transformados pelo algoritmo MinMaxScaler.
# Treinando classificadores, a partir da escala, e da técnica de Feature Selection utilizada.
resultsSS = classifiersTraining (
features = trainFeaturesSS,
tTarget = trainTarget
)
# Plotando os scores, da acurácia dos classificadores treinados, em boxplots.
plotBoxplot(data = resultsSS[0])
O algoritmo XGBoost, foi o que obteve a melhor acurácia, para o conjunto dados transformados pelo algoritmo StandardScaler.
# Treinando classificadores, a partir da escala, e da técnica de Feature Selection utilizada.
resultsND = classifiersTraining (
features = trainFeaturesNormDistribuition,
tTarget = trainTarget
)
# Plotando os scores, da acurácia dos classificadores treinados, em boxplots.
plotBoxplot(data = resultsND[0])
O algoritmo XGBoost, foi o que obteve a melhor acurácia, para o conjunto dados transformados pelo algoritmo Box-Cox.
# Treinando classificadores, a partir da escala, e da técnica de Feature Selection utilizada.
resultsNorm = classifiersTraining (
features = trainFeaturesNormalized,
tTarget = trainTarget
)
# Plotando os scores, da acurácia dos classificadores treinados, em boxplots.
plotBoxplot(data = resultsNorm[0])
O algoritmo XGBoost, foi o que obteve a melhor acurácia, para o conjunto dados transformados pelo algoritmo Normalize.
Agora que já testamos diferentes algoritmos com diversas escalas, iremos escolher os melhores modelos criados e otimizar seus parâmetros. A partir dos testes anteriores, notamos que os algoritmos baseados em árvores de decisão apresentaram os melhores resultados. Em parte, isso se justifica pelo desbalanceamento dos registros das classes da variável a ser prevista.
Para validar estas teorias, iremos criar modelos baseados nos algoritmos Logist Regression, Random Forest e XGBoost. A função Log Loss será utilizada para avaliar o custo dos modelos, isto é, previsões incorretas de maneira muito confiante terão penalidades maiores. A acurácia dos modelos apenas será uma métrica adicional calculada durante o treinamento.
Iremos buscar pelos melhores parâmetros, para criar um modelo com o algoritmo de Regressão Logística.
# Definindo qual conjunto de dados de treino, já escalado, deve ser utilizado e a sua variável target.
trainX = trainFeaturesMM
trainY = trainTarget
# Definindo qual conjunto de dados de teste, já escalado, deve ser utilizado e a sua variável target.
testX = testFeaturesMM
testY = testTarget
# Definindo os valores que devem ser testados, em cada um dos parâmetros do modelo especificado.
paramGrid = dict (
penalty = ['l1', 'l2'],
C = [15, 16, 17, 18, 19, 20],
solver = ['newton-cg', 'sag', 'saga', 'lbfgs'],
random_state = [0],
tol = [0.0000010, 0.0000015, 0.0000020, 0.0000025],
max_iter = [25, 26, 27, 28, 29, 30]
)
# Criando uma instância da classe do modelo de Regressão Logística.
model = LogisticRegression()
# Criando o grid, para fazer a busca dos melhores parâmetros para o modelo.
grid = GridSearchCV(estimator = model, param_grid = paramGrid, cv = 10, verbose = True, n_jobs = -1)
# Buscando pelos melhores parâmetros para o modelo.
grid.fit(trainX, trainY)
# Exibindo a configuração, do melhor modelo treinado.
print("\n" + "Melhores Parâmetros para o Modelo:" + "\n\n", grid.best_estimator_)
# Criando o modelo, com a melhor configuração encontrada.
classifierLR = grid.best_estimator_
# Treinando o modelo com os dados de treino.
classifierLR.fit(X = trainX, y = trainY)
# Calculando a acurácia do modelo para o conjunto de dados de treino.
scoreTrainLR = accuracy_score(trainY, classifierLR.predict(trainX))
scoreTrainLRLL = log_loss(list(trainY), classifierLR.predict_proba(trainX))
# Visualizando o resultado.
print('Acurácia para os dados de treino: ' + str(scoreTrainLR))
print('Log Loss para os dados de treino: ' + str(scoreTrainLRLL))
# Definindo os labels reais e os previstos pelo modelo.
columns = pd.Series(trainY)
index = pd.Series(classifierLR.predict(trainX))
# Definindo o nome das Séries de conjuntos de dados.
columns.name = 'Actual'
index.name = 'Predicted'
# Criando um CrossTab com os resultados gerados.
crossTabTrainLR = pd.crosstab(columns = columns, index = index)
# Exibindo a CrossTab.
crossTabTrainLR
# Calculando a acurácia do modelo para o conjunto de dados de teste.
scoreTestLR = accuracy_score(testY, classifierLR.predict(testX))
scoreTestLRLL = log_loss(list(testY), classifierLR.predict_proba(testX))
# Visualizando o resultado.
print('Acurácia para os dados de teste: ' + str(scoreTestLR))
print('Log Loss para os dados de teste: ' + str(scoreTestLRLL))
# Definindo os labels reais e os previstos pelo modelo.
columns = pd.Series(testY)
index = pd.Series(classifierLR.predict(testX))
# Definindo o nome das Séries de conjuntos de dados.
columns.name = 'Actual'
index.name = 'Predicted'
# Criando um CrossTab com os resultados gerados.
crossTabTestLR = pd.crosstab(columns = columns, index = index)
# Exibindo a CrossTab.
crossTabTestLR
Iremos buscar pelos melhores parâmetros, para criar um modelo com o algoritmo Random Forest.
# Definindo qual conjunto de dados de treino, já escalado, deve ser utilizado e a sua variável target.
trainX = trainFeaturesMM
trainY = trainTarget
# Definindo qual conjunto de dados de teste, já escalado, deve ser utilizado e a sua variável target.
testX = testFeaturesMM
testY = testTarget
# Definindo os valores que devem ser testados, em cada um dos parâmetros do modelo especificado.
paramGrid = dict (
n_estimators = [102],
max_depth = [None, 2, 3],
criterion = ['gini', 'entropy'],
max_features = ['auto', 'sqrt', 'log2'],
min_samples_split = [3],#3, 4],
min_samples_leaf = [5]
)
# Criando uma instância da classe do modelo Random Forest.
model = RandomForestClassifier()
# Criando o grid, para fazer a busca dos melhores parâmetros para o modelo.
grid = GridSearchCV(estimator = model, param_grid = paramGrid, cv = 10, verbose = True, n_jobs = -1)
# Buscando pelos melhores parâmetros para o modelo.
grid.fit(trainX, trainY)
# Exibindo a configuração, do melhor modelo treinado.
print("\n" + "Melhores Parâmetros para o Modelo:" + "\n\n", grid.best_estimator_)
# Criando o modelo, com a melhor configuração encontrada.
classifierRF = grid.best_estimator_
# Treinando o modelo com os dados de treino.
classifierRF.fit(X = trainX, y = trainY)
# Calculando a acurácia do modelo para o conjunto de dados de treino.
scoreTrainRF = accuracy_score(trainY, classifierRF.predict(trainX))
scoreTrainRFLL = log_loss(list(trainY), classifierRF.predict_proba(trainX))
# Visualizando o resultado.
print('Acurácia para os dados de treino: ' + str(scoreTrainRF))
print('Log Loss para os dados de treino: ' + str(scoreTrainRFLL))
# Definindo os labels reais e os previstos pelo modelo.
columns = pd.Series(trainY)
index = pd.Series(classifierRF.predict(trainX))
# Definindo o nome das Séries de conjuntos de dados.
columns.name = 'Actual'
index.name = 'Predicted'
# Criando um CrossTab com os resultados gerados.
crossTabTrainRF = pd.crosstab(columns = columns, index = index)
# Exibindo a CrossTab.
crossTabTrainRF
# Calculando a acurácia do modelo para o conjunto de dados de teste.
scoreTestRF = accuracy_score(testY, classifierRF.predict(testX))
scoreTestRFLL = log_loss(list(testY), classifierRF.predict_proba(testX))
# Visualizando o resultado.
print('Acurácia para os dados de teste: ' + str(scoreTestRF))
print('Log Loss para os dados de teste: ' + str(scoreTestRFLL))
# Definindo os labels reais e os previstos pelo modelo.
columns = pd.Series(testY)
index = pd.Series(classifierRF.predict(testX))
# Definindo o nome das Séries de conjuntos de dados.
columns.name = 'Actual'
index.name = 'Predicted'
# Criando um CrossTab com os resultados gerados.
crossTabTestRF = pd.crosstab(columns = columns, index = index)
# Exibindo a CrossTab.
crossTabTestRF
Iremos buscar pelos melhores parâmetros, para criar um modelo com algoritmo Xgboost.
# Definindo qual conjunto de dados de treino, já escalado, deve ser utilizado e a sua variável target.
trainX = trainFeaturesMM
trainY = trainTarget
# Definindo qual conjunto de dados de teste, já escalado, deve ser utilizado e a sua variável target.
testX = testFeaturesMM
testY = testTarget
# Definindo os valores que devem ser testados, em cada um dos parâmetros do modelo especificado.
paramGrid = dict (
missing = [np.nan],
booster = ['gbtree', 'gblinear', 'dart'],
max_depth = [6],
n_estimators = [220],
learning_rate = [0.02],
nthread = [4],
gamma = [0.01],
subsample = [0.7],
eval_metric = ['mlogloss', 'merror'],
colsample_bytree = [.9],
seed = [100]
)
# Criando uma instância da classe do modelo Random Forest.
model = xgb.XGBClassifier()
# Criando o grid, para fazer a busca dos melhores parâmetros para o modelo.
grid = GridSearchCV(estimator = model, param_grid = paramGrid, cv = 10, verbose = True, n_jobs = -1)
# Buscando pelos melhores parâmetros para o modelo.
grid.fit(trainX, trainY)
# Exibindo a configuração, do melhor modelo treinado.
print("\n" + "Melhores Parâmetros para o Modelo:" + "\n\n", grid.best_estimator_)
# Criando o modelo, com a melhor configuração encontrada.
classifierXGB = grid.best_estimator_
classifierXGB.fit(X = trainX, y = trainY)
# Calculando a acurácia do modelo para o conjunto de dados de treino.
scoreTrainXGB = accuracy_score(trainY, classifierXGB.predict(trainX))
scoreTrainXGBLL = log_loss(list(trainY), classifierXGB.predict_proba(trainX))
# Visualizando o resultado.
print('Acurácia para os dados de treino: ' + str(scoreTrainXGB))
print('Log Loss para os dados de treino: ' + str(scoreTrainXGBLL))
# Definindo os labels reais e os previstos pelo modelo.
columns = pd.Series(trainY)
index = pd.Series(classifierXGB.predict(trainX))
# Definindo o nome das Séries de conjuntos de dados.
columns.name = 'Actual'
index.name = 'Predicted'
# Criando um CrossTab com os resultados gerados.
crossTabTestXGB = pd.crosstab(columns = columns, index = index)
# Exibindo a CrossTab.
crossTabTestXGB
# Calculando a acurácia do modelo para o conjunto de dados de teste.
scoreTestXGB = accuracy_score(testY, classifierXGB.predict(testX))
scoreTestXGBLL = log_loss(list(testY), classifierXGB.predict_proba(testX))
# Visualizando o resultado.
print('Acurácia para os dados de teste: ' + str(scoreTestXGB)) # 0.8340217799474278
print('Log Loss para os dados de teste: ' + str(scoreTestXGBLL))
# Definindo os labels reais e os previstos pelo modelo.
columns = pd.Series(testY)
index = pd.Series(classifierXGB.predict(testX))
# Definindo o nome das Séries de conjuntos de dados.
columns.name = 'Actual'
index.name = 'Predicted'
# Criando um CrossTab com os resultados gerados.
crossTabTestXGB = pd.crosstab(columns = columns, index = index)
# Exibindo a CrossTab.
crossTabTestXGB
O melhor classificador treinado, utiliza o algoritmo XGBoost com as features normalizadas. Salvaremos as configurações desse modelo em um arquivo .sav.
# Salvando o modelo preditivo especificado.
saveModel(name = 'classifierXGB', model = classifierXGB)
Caso deseje pular as etapas anteriores de treinamento, execute o comando a seguir, para carregar o modelo já treinado.
# Carregando o modelo preditivo especificado.
classifierXGB = loadModel(name = 'classifierXGB')
Para analisar melhor a performance do modelo, precisamos determinar os valores das probabilidades geradas nas previsões.
# Calculando a acurácia do modelo para o conjunto de dados de treino.
scoreTrainXGB = accuracy_score(trainY, classifierXGB.predict(trainX))
scoreTrainXGBLL = log_loss(list(trainY), classifierXGB.predict_proba(trainX))
# Visualizando o resultado.
print('Acurácia para os dados de treino: ' + str(scoreTrainXGB))
print('Log Loss para os dados de treino: ' + str(scoreTrainXGBLL))
# Calculando a acurácia do modelo para o conjunto de dados de teste.
scoreTestXGB = accuracy_score(testY, classifierXGB.predict(testX))
scoreTestXGBLL = log_loss(list(testY), classifierXGB.predict_proba(testX))
# Visualizando o resultado.
print('Acurácia para os dados de teste: ' + str(scoreTestXGB))
print('Log Loss para os dados de teste: ' + str(scoreTestXGBLL))
# Definindo os labels reais e os previstos pelo modelo.
columns = pd.Series(testY)
index = pd.Series(classifierXGB.predict(testX))
# Definindo o nome das Séries de conjuntos de dados.
columns.name = 'Actual'
index.name = 'Predicted'
# Criando dicionário para renomear os valores da variável preditora.
map = {
0: 'Entire home/apt',
1: 'Hotel room',
2: 'Private room',
3: 'Shared room'
}
# Criando um dataframe com o conjunto de dados da variável preditora e o conjunto de dados previsto.
table = pd.concat(
objs = [
columns.reset_index().drop(['index'], axis = 1),
index.reset_index().drop(['index'], axis = 1)
],
axis = 1
)
# Renomeando os valores do conjunto de dados.
for c in table.columns:
table[c] = [map[i] for i in table[c]]
# Exibindo a CrossTab.
pd.crosstab(columns = table['Actual'], index = table['Predicted'])
Finalizamos esta análise, concluindo que o algoritmo XGBoost, gerou o modelo com o menor score para a métrica Log Loss. Os scores alcançados para os conjuntos de dados foram:
Caso tenha alguma dúvida, sugestão ou apenas queira trocar uma ideia sobre este projeto, não hesite em entrar em contato comigo!